#ifndef ELEMENT_H
#define ELEMENT_H

#include "vecmath.h"
#include "boundingbox.h"
#include "vertexarray.h"
#include "factories.h"

class Element
{
public:
    Element();
    Element(const BoundingBox& boundingBox, VertexArray* vertexArray = NULL);
    ~Element();
    
    const VertexArray* getVertexArray() const { return vertexArray; }
    void setVertexArray(VertexArray* vertexArray) { this->vertexArray = vertexArray; }
    
    void assign(VertexArray* destination, unsigned& verticesIndex, unsigned& indicesIndex);
    unsigned getVerticesIndex() const { return verticesIndex; }
    unsigned getVerticesSize() const { return (vertexArray ? vertexArray->getVerticesSize() : verticesSize); }
    unsigned getIndicesIndex() const { return indicesIndex; }
    unsigned getIndicesSize() const { return (vertexArray ? vertexArray->getIndicesSize() : indicesSize); }
    
    unsigned getIndex() const { return (indicesSize ? indicesIndex : verticesIndex); }
	
	bool getDimmed() const { return dimmed; }
	void setDimmed(bool flag) { dimmed = flag; }
	
	virtual QString getDescription() const { return "No Description"; }
	virtual QString getSecondaryDescription() const { return "No Secondary Description"; }
	virtual void getColor(Color4b out) const { ColorFactory::instance().getStateColor(out); }
	void getFinalColor(Color4b out) const { getColor(out); if (dimmed) ScaleColor4b(out, out, 0.25); }
	
	enum ElementType { EventType, StateType, MutexType };
	
	virtual ElementType getType() const = 0;
    
public:
    BoundingBox boundingBox;
	unsigned index;
    
protected:
    VertexArray* vertexArray;
    unsigned verticesIndex;
    unsigned verticesSize;
    unsigned indicesIndex;
    unsigned indicesSize;
	
	bool dimmed;
};

class Event : public Element
{
public:
    Event(const QString& classDescription, const QString& typeDescription);
	QString getDescription() const { return classDescription; }
	QString getSecondaryDescription() const { return typeDescription; }
	void getColor(Color4b out) const { ColorFactory::instance().getColor(out, "event", classDescription); }
	
	ElementType getType() const { return EventType; }
    
public:
	QString classDescription;
	QString typeDescription;
};

class State : public Element
{
public:
    State(unsigned eventStart, unsigned eventEnd, const QString& description = "No Description");
	QString getDescription() const { return description; }
	void getColor(Color4b out) const { ColorFactory::instance().getColor(out, "state", description); }
	
	ElementType getType() const { return StateType; }
    
public:
	unsigned length;
	QString description;
};

class Mutex : public Element
{
public:
	Mutex(const QString& symbol, unsigned eventStart, unsigned eventEnd, unsigned level);
	QString getDescription() const { return symbol; }
	
	ElementType getType() const { return MutexType; }
    
public:
	unsigned length;
	QString symbol;
};

#endif // ELEMENT_H
